package auth

import (
	"context"
	"sort"

	"gitee.com/liuxuezhan/ar-platform/base-common/headInfo"

	"gitee.com/liuxuezhan/ar-platform/admin-api/internal/svc"
	"gitee.com/liuxuezhan/ar-platform/admin-api/internal/types"
	"gitee.com/liuxuezhan/ar-platform/admin-api/pkg/sliceH"
	v1 "gitee.com/liuxuezhan/ar-platform/rpc-client/authRoleClient/api/role/v1"

	"github.com/zeromicro/go-zero/core/logx"
)

const (
	PerIdentMenu = "menu"        // 目录菜单按钮标识
	PerIdentData = "data_access" // 数据访问标识
)

type GetAccountMenuTreeLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewGetAccountMenuTreeLogic 获取账户菜单权限树
func NewGetAccountMenuTreeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAccountMenuTreeLogic {
	return &GetAccountMenuTreeLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetAccountMenuTreeLogic) GetAccountMenuTree(req *types.GetAccountMenuTreeRequest) (resp *types.GetAccountMenuTreeResponse, err error) {
	// 获取账户的角色ids
	roleIdsReply, err := l.svcCtx.AuthRoleRpc.GetAccountRoleIds(l.ctx, &v1.GetAccountRoleIdsRequest{
		AccountId:   headInfo.GetTokenUid(l.ctx),
		AccountType: v1.AccountType(req.AccountType),
	})
	if err != nil {
		return nil, err
	}

	if len(roleIdsReply.RoleIds) == 0 {
		return &types.GetAccountMenuTreeResponse{}, nil
	}

	// 获取角色的菜单权限ids
	var menuPermissionIds []int64
	for _, roleId := range roleIdsReply.GetRoleIds() {
		permissionIdsReply, err := l.svcCtx.AuthRoleRpc.GetRolePermissionIds(l.ctx, &v1.GetRolePermissionIdsRequest{
			RoleId:               roleId,
			PermissionIdentifier: PerIdentMenu,
		})
		if err != nil {
			return nil, err
		}

		menuPermissionIds = append(menuPermissionIds, permissionIdsReply.GetPermissionIds()...)
	}

	// 获取拥有权限的菜单ids
	checkMap := map[int64]bool{}
	for _, menuPermissionId := range sliceH.Distinct(menuPermissionIds) {
		menuIdsReply, err := l.svcCtx.AuthRoleRpc.GetPermissionFunctionIds(l.ctx, &v1.GetPermissionFunctionIdsRequest{PermissionId: menuPermissionId})
		if err != nil {
			return nil, err
		}

		for _, id := range menuIdsReply.GetFunctionIds() {
			checkMap[id] = true
		}
	}

	data, err := l.svcCtx.AuthRoleRpc.GetAllMenu(l.ctx, &v1.GetAllMenuRequest{})
	if err != nil {
		return nil, err
	}

	resp = &types.GetAccountMenuTreeResponse{}
	// resp.Data = l.CreateMenuTree(data.Data, checkMap)
	resp.Data = l.CreateMenuTreeShow(data.Data, checkMap)
	return resp, nil
}

// CreateMenuTree 生成菜单模块树
func (l *GetAccountMenuTreeLogic) CreateMenuTree(allMenus []*v1.AllMenu, checkMap map[int64]bool) (res []types.AccountMenu) {
	var m = map[int64][]*v1.AllMenu{}
	for _, menu := range allMenus {
		m[menu.MenuPid] = append(m[menu.MenuPid], menu)
	}

	var recursive func(topId int64) []types.AccountMenu
	recursive = func(topId int64) []types.AccountMenu {
		var tree []types.AccountMenu
		if menus, ok := m[topId]; ok {
			sort.Slice(menus, func(i, j int) bool {
				return menus[i].ListOrder < menus[j].ListOrder
			})
			for _, menu := range menus {
				temp := types.AccountMenu{
					Id:        menu.Id,
					MenuPid:   menu.MenuPid,
					MenuName:  menu.MenuName,
					MenuType:  int8(menu.MenuType),
					Target:    int8(menu.Target),
					Url:       menu.Url,
					Icon:      menu.Icon,
					ListOrder: menu.ListOrder,
					Visible:   int8(menu.Visible),
					Refresh:   int8(menu.Refresh),
					Checked:   checkMap[menu.Id],
					ChildTree: recursive(menu.Id),
				}
				tree = append(tree, temp)
			}
		}
		return tree
	}

	return recursive(0)
}

// CreateMenuTree 生成菜单模块树
func (l *GetAccountMenuTreeLogic) CreateMenuTreeShow(allMenus []*v1.AllMenu, checkMap map[int64]bool) (res []types.AccountMenu) {
	var m = map[int64][]*v1.AllMenu{}
	for _, menu := range allMenus {
		m[menu.MenuPid] = append(m[menu.MenuPid], menu)
	}

	var recursive func(topId int64) []types.AccountMenu
	recursive = func(topId int64) []types.AccountMenu {
		var tree []types.AccountMenu
		if menus, ok := m[topId]; ok {
			sort.Slice(menus, func(i, j int) bool {
				return menus[i].ListOrder < menus[j].ListOrder
			})
			for _, menu := range menus {
				if checkMap[menu.Id] {
					temp := types.AccountMenu{
						Id:        menu.Id,
						MenuPid:   menu.MenuPid,
						MenuName:  menu.MenuName,
						MenuType:  int8(menu.MenuType),
						Target:    int8(menu.Target),
						Url:       menu.Url,
						Icon:      menu.Icon,
						ListOrder: menu.ListOrder,
						Visible:   int8(menu.Visible),
						Refresh:   int8(menu.Refresh),
						Checked:   checkMap[menu.Id],
						ChildTree: recursive(menu.Id),
					}
					tree = append(tree, temp)
				}
			}
		}
		return tree
	}

	return recursive(0)
}
